package cn.mulanbay.business.handler.bloom;

import com.google.common.hash.Funnels;
import cn.mulanbay.business.handler.BaseHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;

import java.nio.charset.Charset;
import java.util.List;

/**
 * 布隆过滤器redis实现
 *
 * @author fenghong
 * @create 2022-01-16 10:00
 */
public class RedisBloomHandler extends BaseHandler {

    @Value("${filter.bloom.expectNums:1000}")
    int expectNums;

    @Value("${filter.bloom.fpp:0.02}")
    double fpp;

    @Autowired
    private RedisTemplate redisTemplate;

    private BloomFilterHelper<String> bloomFilterHelper;

    public RedisBloomHandler() {
        super("布隆过滤器");
    }

    @Override
    public void init() {
        bloomFilterHelper = new BloomFilterHelper(Funnels.stringFunnel(Charset.defaultCharset()), expectNums, fpp);
    }

    /**
     * 根据value值放入布隆过滤器中
     *
     * @param key
     * @param value
     * @return
     */
    public void addBloomKeys(String key, String value) {
        int[] bit = bloomFilterHelper.RedisHashFunction(value);
        for (int i : bit) {
            redisTemplate.opsForValue().setBit(key, i, true);
        }
    }

    /**
     * 根据value值列表放入布隆过滤器中
     *
     * @param key
     * @param value
     * @return
     */
    public void addBloomKeysList(String key, List<String> value) {
        for (String v : value) {
           this.addBloomKeys(key,v);
        }
    }

    /**
     * 根据同样的传入值得到同样的bit数组，然后判断bit位是否为1
     *
     * @param key
     * @param value
     * @return
     */
    public boolean getBloomKeys(String key, String value) {
        int[] bit = bloomFilterHelper.RedisHashFunction(value);
        for (int i : bit) {
            if (!redisTemplate.opsForValue().getBit(key, i)) {
                return false;
            }
        }
        return true;
    }
}
